/*
 * @ModuleName: Custom Table
 * @Author: yuetchn@163.com
 * @LastEditTime: 2023-04-21 22:09:42
 */
import { defineComponent, onMounted, watch, reactive, ref, toRefs, unref } from "vue";
import Sortable from "sortablejs"
import { ElTable, ElTableColumn, ElLoading } from "element-plus"
import { tableProps, tableEmits } from "./options";

export default defineComponent({
  props: tableProps,
  emits: tableEmits,
  setup(props, { emit }) {
    const tableRef = ref<InstanceType<typeof ElTable>>();
    const state = reactive({
      pageSize: props.pageSize,
      pageNumber: props.pageNumber,
      total: props.total,
    });

    watch(() => props.total, (v) => {
      state.total = v
    }, { immediate: true });

    watch(() => props.pageNumber, (v) => {
      state.pageNumber = v;
    }, { immediate: true });

    watch(() => props.pageSize, (v) => {
      state.pageSize = v;
    }, { immediate: true });

    let tableLoading: any = null

    const clearSelection = () => tableRef.value?.clearSelection();
    const toggleRowSelection = (...args: any[]) => tableRef.value?.toggleRowSelection(args[0], args[1]);
    const toggleAllSelection = () => tableRef.value?.toggleAllSelection();
    const toggleRowExpansion = (...args: any[]) => tableRef.value?.toggleRowExpansion(args[0], args[1]);
    const setCurrentRow = (...args: any[]) => tableRef.value?.setCurrentRow(args);
    const clearSort = () => tableRef.value?.clearSort();
    const clearFilter = (...args: any[]) => tableRef.value?.clearFilter(args);
    const doLayout = () => tableRef.value?.doLayout();
    const sort = (...args: any[]) => tableRef.value?.sort(args[0], args[1]);

    onMounted(() => {
      if (props.drag) {
        const target = unref(tableRef)
        ?.$el
        .querySelector(".ElTable__body-wrapper tbody") || unref(tableRef)
        ?.$el
        .querySelector(".el-table__body-wrapper tbody")
        new Sortable(
          target,
          {
            animation: 150,
            filter: ".drag_disabled",
            onEnd: (e) => emit("drag-end", e),
            onStart: (e) => emit("drag-start", e),
          },
        );
      }
    });

    watch(() => props.loading, (v) => {
      if (v) {
        const target = unref(tableRef)
        ?.$el
        .querySelector(".ElTable__body-wrapper") || unref(tableRef)
        ?.$el
        .querySelector(".el-table__body-wrapper")
        tableLoading = ElLoading.service({
          target,
          text: "Loading...",
        });
        return;
      }
      tableLoading && tableLoading.close();
    }, { flush: "post" });

    return {
      // ref
      tableRef,

      // refs
      ...toRefs(state),

      // func
      clearSelection,
      toggleRowSelection,
      toggleAllSelection,
      toggleRowExpansion,
      setCurrentRow,
      clearSort,
      clearFilter,
      doLayout,
      sort,
    };
  },
  render() {
    const props = this.$props;
    const slots = this.$slots;
    const emit = this.$emit;
    const pageChange = () => {
      emit("update:page-size", this.pageSize);
      emit("update:page-number", this.pageNumber);
      emit("page-change");
    };
    const elTableColumns = props.columns?.map((f) => {
      const column = (
        <ElTableColumn
          label={ f.label }
          prop={ f.prop }
          width={ f.width }
          type={ f.type }
          index={ f.index }
          column-key={ f.columnKey }
          min-width={ f.minWidth }
          fixed={ f.fixed }
          render-header={ f.renderHeader }
          sortable={ f.sortable }
          sort-method={ f.sortMethod }
          sort-by={ f.sortBy }
          sort-orders={ f.sortOrders }
          resizable={ f.resizable }
          formatter={ f.formatter }
          show-overflow-tooltip={ f.showOverflowTooltip }
          align={ f.align }
          header-align={ f.headerAlign }
          class-name={ f.className }
          label-class-name={ f.labelClassName }
          selectable={ f.selectable }
          reserve-selection={ f.reserveSelection }
          filters={ f.filters }
          filter-placement={ f.filterPlacement }
          filter-multiple={ f.filterMultiple }
          filter-method={ f.filterMethod }
          filter-value={ f.filterdValue }
        ></ElTableColumn>
      );
      if (f.slot) {
        const column_slot = slots[f.prop];
        const header_slot = slots[`${ f.prop }-header`]
        return <column v-slots={ {
          default: column_slot,
          header: header_slot,
        } }
        ></column>;
      }
      return column;
    });

    return (
      <div class="g_table_root">
        {/* 头部,表单查询 - 默认插槽#default */ }
        <div class="g_table_nav">{ slots.default?.() }</div>
        <div class="g_table_table">
          <ElTable
            ref="tableRef"
            data={ props.data }
            height={ props.maxHeight ? undefined : props.height }
            max-height={ props.maxHeight }
            stripe={ props.stripe }
            border={ props.border }
            size={ props.size }
            fit={ props.fit }
            show-header={ props.showHeader }
            highlight-current-row={ props.highlightCurrentRow }
            current-row-key={ props.currentRowKey }
            row-class-name={ props.rowClassName }
            row-style={ props.rowStyle }
            cell-class-name={ props.cellClassName }
            cell-style={ props.cellStyle }
            header-row-class-name={ props.headerRowClassName }
            header-row-style={ props.headerRowStyle }
            header-cell-class-name={ props.headerCellClassName }
            header-cell-style={ props.headerCellStyle }
            row-key={ props.rowKey }
            empty-text={ props.emptyText }
            default-expand-all={ props.defaultExpandAll }
            default-sort={ props.defaultSort }
            tooltip-effect={ props.tooltipEffect }
            show-summary={ props.showSummary }
            sum-text={ props.sumText }
            summary-method={ props.summaryMethod }
            span-method={ props.spanMethod }
            select-on-indeterminate={ props.selectOnIndeterminate }
            indent={ props.indent }
            lazy={ props.lazy }
            load={ props.load }
            tree-props={ props.treeProps }
            onSelect={ (...args: any[]) => {
              emit("select", ...args)
            } }
            onSelect-all={ (...args: any[]) => {
              emit("select-all", ...args)
            } }
            onSelection-change={ (...args: any[]) => {
              emit("selection-change", ...args)
            } }
            onCell-mouse-enter={ (...args: any[]) => {
              emit("cell-mouse-enter", ...args)
            } }
            onCell-mouse-leave={ (...args: any[]) => {
              emit("cell-mouse-leave", ...args)
            } }
            onCell-click={ (...args: any[]) => {
              emit("cell-click", ...args)
            } }
            onCell-dblclick={ (...args: any[]) => {
              emit("cell-dblclick", ...args)
            } }
            onCell-contextmenu={ (...args: any[]) => {
              emit("cell-contextmenu", ...args)
            } }
            onRow-click={ (...args: any[]) => {
              emit("row-click", ...args)
            } }
            onRow-contextmenu={ (...args: any[]) => {
              emit("row-contextmenu", ...args)
            } }
            onRow-dblclick={ (...args: any[]) => {
              emit("row-dblclick", ...args)
            } }
            oHeader-click={ (...args: any[]) => {
              emit("header-click", ...args)
            } }
            onHeader-contextmenu={ (...args: any[]) => {
              emit("header-contextmenu", ...args)
            } }
            onSort-change={ (...args: any[]) => {
              emit("sort-change", ...args)
            } }
            onFilter-change={ (...args: any[]) => {
              emit("filter-change", ...args)
            } }
            onCurrent-change={ (...args: any[]) => {
              emit("current-change", ...args)
            } }
            onHeader-dragend={ (...args: any[]) => {
              emit("header-dragend", ...args)
            } }
            onExpand-change={ (...args: any[]) => {
              emit("expand-change", ...args)
            } }
          >
            { elTableColumns }
          </ElTable>
        </div>
        {/* 底部,Page分页 */ }
        <div v-show={ props.page && props.total > 0 } class="g_table_page">
          <g-page page-align={ props.pageAlign } v-model:page-number={ this.pageNumber } v-model:page-size={ this.pageSize } v-model:total={ this.total } onChange={ () => pageChange() }></g-page>
        </div>
      </div>
    );
  },
});
